import { getGuid } from '@/utils/public'
import { getCustomComDesignInfo } from '../axios'
import {
  getComDefaultOptions,
  BwComTypeEnum,
  BwCustomComPropDataTypeEnum,
  BwCustomComNodeAttrFromTypeEnum,
  BwCustomComNodeAttrDataTypeEnum,
  type BwCustomComNodeAttrModel,
  type BwCustomComStructModel,
  type BwCustomComNodeEnableSlotInfoModel,
} from '@bitwit/base-com-render'

import type { BwDesignDragAddNodeModel } from './model'

const htmlDefaultCss = `/**
* 温馨提示：在这里编写你的页面样式。
* 你可以点击面板上方的「使用帮助」了解。
*/
.bw-container {
    width: 100%;
    height: 100%;
    min-height: 32px;
}`

function crateNodeInfo(
  data: BwDesignDragAddNodeModel,
  defOptions: Record<string, any>
) {
  const eleInfo: BwCustomComStructModel = {
    nodeId: getGuid(),
    comName: data.dragComCode,
    comType: data.dragComType,
    comAppCode: data.dragComAppCode,
    nodeName: data.dragComName,
    parentNodeId: data.toNodeId,
    parentNodeSlotCode: data.toNodeSlotCode,

    style: null,
    children: null,

    css: defOptions.css,
    attrs: defOptions.attrs,
    enableSlotList: defOptions.enableSlotList,
  }
  return eleInfo
}

export function customComPropDataTypeToNodeAttrDataType(
  type?: BwCustomComPropDataTypeEnum
): BwCustomComNodeAttrDataTypeEnum | null {
  switch (type) {
    case BwCustomComPropDataTypeEnum.array: {
      return BwCustomComNodeAttrDataTypeEnum.array
    }
    case BwCustomComPropDataTypeEnum.boolean: {
      return BwCustomComNodeAttrDataTypeEnum.boolean
    }
    case BwCustomComPropDataTypeEnum.function: {
      return BwCustomComNodeAttrDataTypeEnum.function
    }
    case BwCustomComPropDataTypeEnum.number: {
      return BwCustomComNodeAttrDataTypeEnum.number
    }
    case BwCustomComPropDataTypeEnum.object: {
      return BwCustomComNodeAttrDataTypeEnum.object
    }
    case BwCustomComPropDataTypeEnum.string: {
      return BwCustomComNodeAttrDataTypeEnum.string
    }
    default: {
      return null
    }
  }
}

/** 生成节点元素 */
export function createDesignNodeEle(
  data: BwDesignDragAddNodeModel
): Promise<BwCustomComStructModel> {
  return new Promise<BwCustomComStructModel>((resolve, reject) => {
    if (data.dragComType === BwComTypeEnum.custom) {
      getCustomComDesignInfo(data.dragComAppCode ?? '', data.dragComCode)
        .then((res) => {
          if (res) {
            const curSlotList = res.comSlots
            const curPropsList = res.comProps

            const curProps: Record<string, BwCustomComNodeAttrModel> = {}
            const enableSlotList: Array<BwCustomComNodeEnableSlotInfoModel> = []
            if (Array.isArray(curSlotList) && curSlotList.length) {
              curSlotList.forEach((item) => {
                enableSlotList.push({ ...item, visible: true })
              })
            }

            if (Array.isArray(curPropsList) && curPropsList.length) {
              curPropsList.forEach((item) => {
                const attrValueDataType =
                  customComPropDataTypeToNodeAttrDataType(
                    item.defaultValueDataType ?? undefined
                  )
                if (attrValueDataType) {
                  curProps[item.key] = {
                    isModel: !!item.isModel,
                    valueFromType: BwCustomComNodeAttrFromTypeEnum.constValue,
                    valueDataType: attrValueDataType,
                    constValue: item.defaultValue ?? undefined,
                  }
                }
              })
            }

            const eleInfo = crateNodeInfo(data, {
              attrs: curProps,
              enableSlotList,
            })
            resolve(eleInfo)
          } else {
            reject(`获取自定义组件失败， 请检查！`)
          }
        })
        .catch(() => {
          reject(`获取自定义组件失败， 请检查！`)
        })
    } else {
      const defaultOptions: Record<string, any> = getComDefaultOptions(
        data.dragComType,
        data.dragComCode
      )
      if (data.dragComType === BwComTypeEnum.html) {
        defaultOptions.css = htmlDefaultCss
      }

      const eleInfo = crateNodeInfo(data, defaultOptions)
      resolve(eleInfo)
    }
  })
}
